package com.kehutong.material.admin;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import com.kehutong.material.service.MaterialService;
import org.coraframework.authz.HasPermission;
import org.coraframework.bean.Beans;
import org.coraframework.bean.valid.ValidResult;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSON;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.MvcAction;
import org.coraframework.mvc.http.Bean;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.util.Enums;
import org.coraframework.util.EnumUtil;
import org.coraframework.util.Objects;
import com.kehutong.common.DoveClient;
import com.kehutong.common.entity.Root;
import com.kehutong.common.entity.TreeUtil;
import com.kehutong.common.errcode.Result;
import com.kehutong.common.util.Token;
import com.kehutong.material.entity.Material;
import com.kehutong.material.entity.MaterialPlatform;
import com.kehutong.material.enums.MaterialType;

/**
 * 素材控制器
 * @author: liukunlong
 * @date: 2021-02-19 15:12
 */
@MvcAction
@ReqMapping("/admin/crm/material")
public class MaterialController {
	
	static final Logger logger = LoggerFactory.getLogger(MaterialController.class);
	
	@Inject
	private JdbcSession jdbcSession;
    @Inject
    private DoveClient doveClient;
    @Inject
    private MaterialService materialService;



    @HasPermission("crm:material:view")
    @ReqMapping("/tree")
    public Object listParent(JSONObject jsonObject) {
        String typeJsonStr=jsonObject.getString("type");
        JSONObject typeJson=JSONObject.parseObject(typeJsonStr);
        String type=typeJson.getString("id");
        final List<Material> materialList = jdbcSession.findArray(Material.class)
                .eq("isFolder",true)
                .eq("type",type)
                .eq("deleted", false)
                .exe();
        Material root = Pool.newInstance(Material.class,Root.ROOT_ID);

        MaterialType materialType = EnumUtil.getEnum(MaterialType.class,type);
        root.setName(materialType.getDesc());
        root.setType(materialType);
        root.setDeleted(false);
        materialList.add(root);
        root = TreeUtil.organizeAsTree(materialList, true);
        return Result.success(root);
    }

    @HasPermission("crm:material:view")
    @ReqMapping("/list")
    public Object list(JSONObject jsonObject) throws Exception {
        String pid = jsonObject.getString("pid");
        if (Root.isRoot(pid)) {
            jsonObject.remove("pid");
        }

        //获取枚举类型(前台枚举类型，保存查询一直性？)
        String typeJsonStr=jsonObject.getString("type");
        JSONObject typeJson=JSONObject.parseObject(typeJsonStr);
        String type=typeJson.getString("id");
        return jdbcSession.findPage(Material.class)
    			.eq(jsonObject, "id","pid")
        		.like(jsonObject, "name")
                .between("createTime", jsonObject, "beginTime", "endTime")
                .eq("type",type)
                .eq("isFolder", false)
                .eq("deleted", false)
                .order("createTime", "desc")
                .page(jsonObject)
                .exe();
    }

    @HasPermission("crm:material:view")
    @ReqMapping("/get")
    public Object get(Material item) {
        return item;
    }



    @Bean(newInstance=true, copy=true)
    @HasPermission("crm:material:edit")
    @ReqMapping("/save")
    public Object save(JSONObject item, ValidResult result) {
        return Result.success(materialService.save(item,result));
    }



    @Bean(copy=true)
    @HasPermission("crm:material:edit")
    @ReqMapping("/update")
    public Object update(Material item, ValidResult result) {
	   if (result.hasError("descrition","memory","type","fileId","fileType","isFolder","shareUrl", "userId", "media_id", "expiredTime", "content", "fileId")) {
           return Result.error(0, result.getErrorMessage());
       }

        Material old = Pool.get(Material.class, item.getId());
        if (Objects.nonNull(old)) {
            if (Objects.isEmpty(old.getFileId()) || !old.getFileId().equals(item.getFileId())){
                item.setMedia_id(null);
            }
            item.setFolder(old.isFolder());
        }
        

    	jdbcSession.updateById(item);
        return Result.success();
    }

    //todo 需要考虑不同类型删除问题
    @HasPermission("crm:material:edit")
    @ReqMapping("/delete")
    public Object delete(Material item) throws Exception {
        if (Objects.nonNull(item)) {
            Material material = Pool.get(Material.class, item.getId());
            //如果当前节点的父节点的是根节点则级联删除
            if (Root.isRoot(material.getPid())) {
                item.setDeleted(true);
                jdbcSession.updateById(item);
                List<Material> materialList = jdbcSession.findArray(Material.class)
                        .eq("pid", material.getId())
                        .eq("deleted", false)
                        .exe();

                materialList.forEach(data ->{
                    data.setDeleted(true);
                });
                jdbcSession.updateById(materialList);
            } else {
                item.setDeleted(true);
                jdbcSession.updateById(item);
            }
        }
        return Result.success();
    }

    public static List<String> getNickNames(String contenxt) {
        final char[] chs = contenxt.toCharArray();

        List<String> nameList = new ArrayList<>();
        StringBuilder buf = null;
        for (int i = 0, len = chs.length; i < len; i++) {
            if (chs[i] == '@') {
                buf = new StringBuilder();
            } else if (buf == null) {
                // do nothing
            } else if (Character.isWhitespace(chs[i]) || Character.isSpaceChar(chs[i])) {
                nameList.add(buf.toString());
                buf = null;
            } else {
                buf.append(chs[i]);
            }
        }

        return nameList;
    }

    /**
     * 根据素材信息
     * 群发
     * @throws Exception
     */
    @HasPermission("crm:material:edit")
    @ReqMapping("/send")
    public Object sendMsg(Token token, JSONObject req) throws Exception {
        String typeJsonStr=req.getString("type");
        JSONObject typeJson=JSONObject.parseObject(typeJsonStr);
        String type=typeJson.getString("id");
        String materialId=req.getString("materialId");
        Material material = Pool.get(Material.class,materialId);
        MaterialType materialType=EnumUtil.getEnum(MaterialType.class, type);
        if(materialType.equals(MaterialType.MINI_PROGRAM)){
            if (Objects.isNull(material.getMedia_id()) || (Objects.nonNull(material.getExpiredTime()) && material.getExpiredTime().isBefore(LocalDateTime.now()))) {
                //todo 转存文件
                //materialService.forwordFile(material);
            }
        }
        // 选中业主标志
        JSONArray residentIds = getExternalUserIds(token,req);
        JSONObject result=doveClient.post("/wwin-service/material/wwin/send",(http)->{
            http.addHeader("companyNo",token.getCompanyNo());
            http.addParam("type",type);
            http.addParam("externalUserIds",residentIds.toJSONString());
            http.addParam("chat_type","single");
            JSONObject materialJsonObject = (JSONObject) JSONObject.toJSON(material);
            materialJsonObject.remove("type");
            http.setBody(materialJsonObject.toJSONString());
            //materialJsonObject.forEach((k, v)->http.addParam(k, Objects.nonNull(v)?v.toString():""));
        });
        if(result.getIntValue("code")==200){
            JSONArray failList = result.getJSONArray("data");
            return Result.success(failList);
        }else{
            return Result.error(result.getIntValue("code"),result.getString("message"));
        }
    }

    @HasPermission("crm:material:view")
    @ReqMapping("/get/count")
    public Object getSendMsgCount(Token token, JSONObject req) throws Exception{
        JSONArray externalUserIds = getExternalUserIds(token,req);
        return Result.success(externalUserIds.size());
    }

    /**
     * 发送素材及群发的业主标志数组
     * @param req
     * @return
     */
    private JSONArray getExternalUserIds(Token token,JSONObject req) throws Exception{
        JSONArray externalUserIds = req.getJSONArray("externalUserIds");

        if (externalUserIds.size() == 0) {
            externalUserIds = new JSONArray();
            JSONObject residentResult=doveClient.post("/crm/resident/getResidentList",(http)->{
                http.addHeader("companyNo",token.getCompanyNo());
                http.addParam("classifyId",req.getString("typeId"));
                http.addParam("stateId",req.getString("statusId"));
                http.addParam("tagNames",req.getString("tagNames"));
                //todo 当参数值为null远程调用空指针异常
                if(Objects.nonNull(req.getString("userIds"))){
                    http.addParam("userIds",req.getString("userIds"));
                }
            });
            if(residentResult.getIntValue("code")!=200){
                externalUserIds = new JSONArray();
            }
            JSONArray residentList = residentResult.getJSONObject("data").getJSONArray("list");
            if (Objects.nonEmpty(residentList)) {
                for (Object residentObj : residentList) {
                    JSONObject resident=(JSONObject)residentObj;
                    externalUserIds.add(resident.getString("id"));
                }
            }
        }
        return externalUserIds;
    }


    @HasPermission("crm:material:view")
    @ReqMapping("/get/fail")
    public Object getFailContact(Token token,JSONObject req) throws Exception{
        JSONArray fail_list = req.getJSONArray("contactFailListIds");
        Page<JSONObject> residentPage = new Page<>();
        List<JSONObject> residentList=new ArrayList<>();
        if (Objects.nonEmpty(fail_list)) {
            JSONObject residentResult = doveClient.post("/crm/resident/getResidentList", (http) -> {
                http.addHeader("companyNo",token.getCompanyNo());
                JSONObject body=new JSONObject();
                Integer pageNo = req.getInteger("pageNo");
                Integer pageSize = req.getInteger("pageSize");
                if (Objects.nonNull(pageNo)) {
                    body.put("pageNo", pageNo);
                }
                if (Objects.nonNull(pageSize)) {
                    body.put("pageSize", pageSize);
                }
                body.put("ids", fail_list);
                http.setBody(JSON.toJSONString(body));
            });
            if(residentResult.getIntValue("code")==200){
                JSONArray residentJSONArray = residentResult.getJSONObject("data").getJSONArray("list");
                residentList = JSONObject.parseArray(residentJSONArray.toJSONString(), JSONObject.class);
            }
        }
        residentPage.setList(residentList);
        return Result.success(residentPage);
    }

    @HasPermission("crm:material:reset")
    @ReqMapping("/reset")
    public Object reset(JSONObject jsonObject){
        MaterialType type = Enums.getEnum(MaterialType.class, jsonObject.getString("type"));
        // 1.删除原有的
        List<Material> materialList = jdbcSession.findArray(Material.class)
                                                 .eq("type", type)
                                                 .exe();

        jdbcSession.deleteById(materialList);

        // 2.同步平台的
        List<MaterialPlatform> platformList = jdbcSession.findArray(MaterialPlatform.class)
                                                         .eq("type", type)
                                                         .eq("deleted", false)
                                                         .order("pid", "asc")
                                                         .exe();

        platformList.forEach(e -> {
            Material material = Pool.newInstance(Material.class);
            JSONObject temp = (JSONObject) JSONObject.toJSON(e);
            boolean isFolder = temp.getBooleanValue("folder");
            Beans.from(temp).to(material).igornNull().copy();
            material.setType(type);
            material.setFolder(isFolder);

            jdbcSession.insert(material);
        });

        return Result.success();
    }
}
